Skip to content

Reject compression='jpeg' in to_geotiff (no JPEGTables)#1514

Merged
brendancol merged 1 commit intoxarray-contrib:mainfrom
brendancol:fix-jpeg-tiff-disable
May 8, 2026
Merged

Reject compression='jpeg' in to_geotiff (no JPEGTables)#1514
brendancol merged 1 commit intoxarray-contrib:mainfrom
brendancol:fix-jpeg-tiff-disable

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Pass-8 accuracy sweep finding. The JPEG-in-TIFF write path tags compression=7 (new-style JPEG) but writes a self-contained JFIF stream per tile/strip and never emits the JPEGTables tag (347) that the TIFF spec requires for that codec. libtiff, GDAL, and rasterio all reject the file with TIFFReadEncodedStrip() failed. Our reader round-trips because Pillow decodes the standalone JFIF bytes directly, which masks the break. The user thinks they wrote a TIFF; nothing else can read it.

Repro:
```python
import numpy as np, xarray as xr, rasterio
from xrspatial.geotiff import to_geotiff
arr = np.zeros((32, 32, 3), dtype=np.uint8); arr[..., 0] = 200
da = xr.DataArray(
arr, dims=['y','x','band'],
coords={'y': np.arange(32), 'x': np.arange(32), 'band': [0,1,2]},
attrs={'crs': 4326},
)
to_geotiff(da, '/tmp/x.tif', compression='jpeg', tiled=False)
rasterio.open('/tmp/x.tif').read() # CPLE_AppDefinedError: TIFFReadEncodedStrip() failed
```

Fix: reject compression='jpeg' at the to_geotiff entry point with a clear ValueError pointing at deflate/zstd/lzw. The lower-level _writer.write is untouched so the existing self-decoding tests still cover the codec until someone wires up a JPEGTables-aware encoder.

Test plan

  • new test_to_geotiff_jpeg_rejected covers the user-facing error
  • existing _writer.write JPEG round-trip tests pass unchanged
  • full geotiff suite: 671 passed, 4 skipped (3 unrelated matplotlib deepcopy failures predate this change)

The JPEG-in-TIFF write path tags compression=7 (new-style JPEG) but
writes a self-contained JFIF stream per tile/strip and never emits the
JPEGTables tag (347) that the TIFF spec requires for that codec.
libtiff, GDAL, and rasterio all reject the file with
"TIFFReadEncodedStrip() failed". The internal reader round-trips because
Pillow decodes the standalone JFIF bytes directly, which hides the break
from xrspatial's own tests.

Fix: reject compression='jpeg' at the to_geotiff entry point with a
ValueError that points at deflate/zstd/lzw. The lower-level _writer.write
is untouched so the existing self-decoding tests still demonstrate the
codec works internally; re-enabling the public path needs a
JPEGTables-aware encoder.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 7, 2026
@brendancol brendancol merged commit 998b9cc into xarray-contrib:main May 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant